package com.init.bootframe.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 工具类
 * 
 * @author Administrator
 *
 */
public class TmompUtils {

	/**
	 * 日志
	 */
	private static Logger logger = LoggerFactory.getLogger(TmompUtils.class);

	/**
	 * 获取当前日期
	 * 
	 * @return String
	 */
	public static String getCurrentDate() {
		return getCurrentDate(TmompConstant.BaseDataConstant.FORMATE_DATA1);
	}

	/**
	 * 获取当前日期
	 * 
	 * @param format
	 * 自定义格式
	 * @return String
	 */
	public static String getCurrentDate(String format) {
		Calendar instance = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(instance.getTime());
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 *            需要格式化的字符串
	 * @param originalFormat
	 *            原字符串格式
	 * @param targetFormat
	 *            目标字符串格式
	 * @return
	 */
	public static String formatDate(String date, String originalFormat, String targetFormat) {
		SimpleDateFormat sdf = new SimpleDateFormat(originalFormat);
		try {
			return new SimpleDateFormat(targetFormat).format(sdf.parse(date));
		} catch (ParseException e) {
			logger.error("formatDate() error." + e.getMessage());
		}
		return date;
	}

	/**
	 * 计算两个时间相差多少毫秒
	 * 
	 * @param startTime
	 * @param endTime
	 * @param formatStr
	 * @return
	 * @throws Exception
	 */
	public static long subTime(String startTime, String endTime, String formatStr) throws Exception {
		// yyyy-mm-dd, 会出现时间不对, 因为小写的mm是代表: 秒
		SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
		Date dateTime2 = sdf.parse(startTime);
		Date dateTime1 = sdf.parse(endTime);
		long difference = dateTime2.getTime() - dateTime1.getTime();
		return difference;
	}

	/**
	 * BASE64字符串转化成图片
	 * 
	 * @param imageData
	 * @return
	 * @throws Exception
	 */
	public static void generateImage(String imageData, String path) throws Exception {
		// 图像数据为空
		if (imageData != null && !"".equals(imageData)) {
			BASE64Decoder decoder = new BASE64Decoder();
			OutputStream out = null;
			try {
				// Base64解码
				byte[] b = decoder.decodeBuffer(imageData);
				for (int i = 0; i < b.length; ++i) {
					if (b[i] < 0) {// 调整异常数据
						b[i] += 256;
					}
				}
				out = new FileOutputStream(path);
				out.write(b);
				out.flush();
				logger.info("图片生成成功！" + path);
			} catch (Exception e) {
				logger.error("generateImage() 处理图片失败！ " + e.getMessage());
				throw new Exception("处理图片失败！" + e.getMessage());
			} finally {
				if (null != out) {
					try {
						out.close();
					} catch (IOException e) {
						logger.error("关闭图片流失败" + e.getMessage());
					}
				}
			}
		}
	}

	/**
	 * 图片转化成base64字符串
	 * 
	 * @param imgFile
	 * @return String
	 * @throws Exception
	 */
	public static String getImageStr(String imgFile) throws Exception {// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理
		InputStream in = null;
		byte[] data = null;
		// 读取图片字节数组
		try {
			in = new FileInputStream(imgFile);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			logger.error("GetImageStr() 处理图片失败！ " + e.getMessage());
			throw new Exception("处理图片失败！" + e.getMessage());
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					logger.error("关闭图片流失败" + e.getMessage());
				}
			}
		}
		// 对字节数组Base64编码
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(data);// 返回Base64编码过的字节数组字符串
	}

	/**
	 * Base64字符串转 二进制流
	 *
	 * @param base64String
	 *            Base64
	 * @return base64String
	 * @throws IOException
	 *             异常
	 */
	public static byte[] getStringImageBytes(String base64String) throws IOException {
		BASE64Decoder decoder = new BASE64Decoder();
		return base64String != null ? decoder.decodeBuffer(base64String) : null;
	}

	/**
	 * 递归删除目录下的所有文件及子目录下所有文件
	 * 
	 * @param path
	 *            将要删除的文件目录路劲
	 * @return boolean
	 * 
	 */
	public static boolean deleteDir(String path) {
		File dir = new File(path);
		if (!dir.exists()) {
			return true;
		}
		if (dir.isDirectory()) {
			if (dir.list() != null) {
				String[] children = dir.list();
				if (children != null) {
					// 递归删除目录中的子目录下
					for (int i = 0; i < children.length; i++) {
						boolean success = deleteDir(new File(dir, children[i]));
						if (!success) {
							return false;
						}
					}
				}
			}
		}
		logger.info("delete temp file:" + path);
		// 目录此时为空，可以删除
		return dir.delete();
	}

	/**
	 * 递归删除目录下的所有文件及子目录下所有文件
	 * 
	 * @param dir
	 *            将要删除的文件目录
	 * @return boolean
	 * 
	 */
	public static boolean deleteDir(File dir) {
		if (!dir.exists()) {
			return true;
		}
		if (dir.isDirectory()) {
			if (dir.list() != null) {
				String[] children = dir.list();
				if (children != null) {
					// 递归删除目录中的子目录下
					for (int i = 0; i < children.length; i++) {
						boolean success = deleteDir(new File(dir, children[i]));
						if (!success) {
							return false;
						}
					}
				}
			}
		}
		logger.info("delete temp file:" + dir.getPath());
		// 目录此时为空，可以删除
		return dir.delete();
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 * 
	 * @param fileName
	 *            文件名
	 * @return String
	 */
	public static String readFileReturnString(String fileName) {
		StringBuffer readFileReturnStringBuffer = TmompUtils.readFileReturnStringBuffer(fileName);
		if (null != readFileReturnStringBuffer && !"".equals(readFileReturnStringBuffer.toString())) {
			return TmompUtils.readFileReturnStringBuffer(fileName).toString();
		}
		return null;
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 * 
	 * @param fileName
	 *            文件名
	 * @return StringBuffer
	 */
	public static StringBuffer readFileReturnStringBuffer(String fileName) {
		File file = new File(fileName);
		FileInputStream fis = null;
		InputStreamReader read = null;
		BufferedReader reader = null;
		StringBuffer result = new StringBuffer();
		try {
			fis = new FileInputStream(file);
			read = new InputStreamReader(fis, TmompConstant.BaseDataConstant.INPUT_STREAM_READER_ENCODING);
			reader = new BufferedReader(read);
			int line = 1;
			String tempString = "";
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				// 显示行号
				logger.debug("line " + line + ": " + tempString);
				result.append(tempString.trim());
				line++;
			}
		} catch (IOException e) {
			result = null;
			logger.error("readFileByLines() error." + e.getMessage());
		} finally {
			if (null != fis) {
				try {
					fis.close();
				} catch (IOException e1) {
					logger.error("fis close error." + e1.getMessage());
				}
			}
			if (null != read) {
				try {
					read.close();
				} catch (IOException e1) {
					logger.error("read close error." + e1.getMessage());
				}
			}
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
					logger.error("reader close error." + e1.getMessage());
				}
			}
		}
		return result;
	}

	/**
	 * 复制文件目录
	 * 
	 * @param file
	 *            源目录
	 * @param toFile
	 *            目标目录
	 * @throws Exception
	 */
	public static void copy(File file, File toFile) throws Exception {
		String filepath = file.getAbsolutePath().replaceAll("\\\\", "/");
		String toFilepath = toFile.getAbsolutePath().replaceAll("\\\\", "/");
		int lastIndexOf = filepath.lastIndexOf("/");
		toFilepath = toFilepath + filepath.substring(lastIndexOf, filepath.length());
		if (file.isDirectory()) {
			File copy = new File(toFilepath);
			// 复制文件夹
			if (!copy.exists()) {
				copy.mkdirs();
			}
			File[] listFiles = file.listFiles();
			if (listFiles != null) {
				// 遍历文件夹
				for (File f : listFiles) {
					copy(f, copy);
				}
			}
		} else {
			if (toFile.isDirectory()) {
				// 写文件
				writeFile(file, new File(toFilepath));
			} else {
				// 写文件
				writeFile(file, toFile);
			}
		}
	}

	/**
	 * 复制文件
	 * 
	 * @param file
	 *            源文件对象
	 * @param toFile
	 *            目标文件对象
	 */
	public static void writeFile(File file, File toFile) {
		int a = 0;
		byte[] b = new byte[1024];
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			logger.info("开始复制文件：" + file.getName());
			logger.info("原始文件路径：【" + file.getAbsolutePath() + "】");
			logger.info("目标文件路径：【" + toFile.getAbsolutePath() + "】");
			fis = new FileInputStream(file);
			fos = new FileOutputStream(toFile);
			while ((a = fis.read(b)) != -1) {
				fos.write(b, 0, a);
			}
			fos.flush();
			logger.info("结束复制文件：" + file.getName());
		} catch (FileNotFoundException e) {
			logger.error("writeFile() error." + e.getMessage());
		} catch (IOException e) {
			logger.error("writeFile() error." + e.getMessage());
		} finally {
			if (null != fis) {
				try {
					fis.close();
				} catch (IOException e) {
					logger.error("fis close error." + e.getMessage());
				}
			}
			if (null != fos) {
				try {
					fos.close();
				} catch (IOException e) {
					logger.error("fos close error." + e.getMessage());
				}
			}
		}
	}

	/**
	 * 将字符串写入文件
	 * 
	 * @param filePath
	 * @param strContent
	 */
	public static void writeStringToFile(String filePath, String strContent) {
		FileWriter fw = null;
		BufferedWriter bw = null;
		try {
			File file = new File(filePath);
			if (file.exists()) {
				file.delete();
				file.createNewFile();
			}
			fw = new FileWriter(file, true);
			bw = new BufferedWriter(fw);
			bw.write(strContent);// 往已有的文件上添加字符串
			bw.close();
			fw.close();
			logger.info("文件写入完毕！" + file.getName());
		} catch (FileNotFoundException e) {
			logger.error("writeFile() error." + e.getMessage());
		} catch (IOException e) {
			logger.error("writeFile() error." + e.getMessage());
		} finally {
			if (null != fw) {
				try {
					fw.close();
				} catch (IOException e) {
					logger.error("fis close error." + e.getMessage());
				}
			}
			if (null != bw) {
				try {
					bw.close();
				} catch (IOException e) {
					logger.error("fos close error." + e.getMessage());
				}
			}
		}
	}

	// 过滤utf-8 4字节字符 (微信昵称携带表情时候需要处理下)
	public static String filterEmoji(String source) {
		if (source != null) {
			Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
					Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
			Matcher emojiMatcher = emoji.matcher(source);
			if (emojiMatcher.find()) {
				source = emojiMatcher.replaceAll("?");
				return source;
			}
			return source;
		}
		return source;
	}

	/**
	 * 读取属性文件
	 * 
	 * @param fileName
	 * @return
	 */
	public static Properties loadProperties(String fileName) {
		Properties prop = new Properties();
		InputStream resourceAsStream = null;
		InputStreamReader inputStreamReader = null;
		try {
			logger.debug("load Properties for:" + fileName);
			resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
			inputStreamReader = new InputStreamReader(resourceAsStream,
					TmompConstant.BaseDataConstant.INPUT_STREAM_READER_ENCODING);// 设置编码格式
			prop.load(inputStreamReader);
		} catch (Exception e) {
			logger.error(e.getMessage());
		} finally {
			if (null != inputStreamReader) {
				try {
					inputStreamReader.close();
				} catch (IOException e) {
					logger.error(e.getMessage());
				}
			}
			if (null != resourceAsStream) {
				try {
					resourceAsStream.close();
				} catch (IOException e) {
					logger.error(e.getMessage());
				}
			}
		}
		return prop;
	}

	/**
	 * 数值的百分比计算
	 * 
	 * @param num1
	 *            被除数
	 * @param num2
	 *            除数
	 * @return 百分比结果
	 */
	public static String numPercentageCalculation(double num1, double num2) {
		// 除数不能为0
		if (num2 != 0) {
			double percent = num1 / num2;
			// 获取格式化对象
			NumberFormat nt = NumberFormat.getPercentInstance();
			// 设置百分数精确度2即保留两位小数
			nt.setMinimumFractionDigits(2);
			// 最后格式化并输出
			return nt.format(percent);
		}
		return "";
	}

	/**
	 * 判断值能不能被除
	 * 
	 * @param value
	 *            除数
	 * 
	 * @return Boolean
	 */
	public static Boolean judgeDivision(String value) {
		Boolean isDivision = false;
		if (null != value && !"".equals(value)) {
			if (value.matches("[0-9]+")) {// 判断是否为整数
				if (!"0".equals(value)) {
					isDivision = true;
				}
			} else if (value.indexOf(".") > 0) {
				value = value.replaceAll("0+?$", "");// 去掉多余的0
				value = value.replaceAll("[.]$", "");// 如最后一位是.则去掉
				if (!"0".equals(value)) {
					isDivision = true;
				}
			}
		}
		return isDivision;
	}

	/**
	 * 从字符中获取数字（包含小数点）
	 * 
	 * @param value
	 * 
	 * 
	 * @return String
	 */
	public static String numberExtract(String value) {
		if (null != value && !"".equals(value)) {
			char[] b = value.toCharArray();
			String result = "";
			String Str = "0123456789.";
			for (int i = 0; i < b.length; i++) {
				if ((Str).indexOf(b[i] + "") != -1) {
					result += b[i];
				}
			}
			return result;
		} else {
			return null;
		}
	}

	/**
	 * 数组去重复
	 * 
	 * @param array
	 *            被去重的数组
	 * @return 去重后的数组
	 */
	public static String[] arrayDistinct(String[] array) {
		if (null != array && array.length > 0) {
			List<String> list = new ArrayList<>();
			for (int i = 0; i < array.length; i++) {
				for (int j = i + 1; j < array.length; j++) {
					if (array[i].equals(array[j])) {
						j = ++i;
					}
				}
				list.add(array[i]);
			}
			String[] newStr = (String[]) list.toArray(new String[list.size()]);
			// Arrays.sort(newStr);// 排序
			return newStr;
		}
		return null;
	}

	/***
	 * 生成uid 8位数字
	 */
	public static String generateUID() {
		Random random = new Random();
		String result = "";
		for (int i = 0; i < 8; i++) {
			// 首字母不能为0
			result += (random.nextInt(9) + 1);
		}
		return result;
	}

	/**
	 * 生成短8位UUID 非纯数字
	 * @return
	 */
	public static String generateShortUID() {
		String[] chars = new String[] { "a", "b", "c", "d", "e", "f",
				"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
				"t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
				"6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
				"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
				"W", "X", "Y", "Z" };
		
		StringBuffer shortBuffer = new StringBuffer();
		String uuid = UUID.randomUUID().toString().replace("-", "");
		for (int i = 0; i < 8; i++) {
			String str = uuid.substring(i * 4, i * 4 + 4);
			int x = Integer.parseInt(str, 16);
			shortBuffer.append(chars[x % 0x3E]);
		}
		return shortBuffer.toString();
	 
	}
	
	/**
	 * 跟据小时来增加时间
	 * 
	 * @author chentao 2018年10月15日
	 * @param hour
	 *            要增加的小时
	 * @return Date 改变后的时间
	 */
	public static Date getIncreaseDateByHour(int hour) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + hour);
		return cal.getTime();
	}

	/**
	 * 跟据分来增加时间
	 * 
	 * @author chentao 2018年10月15日
	 * @param minute
	 *            要增加的分钟
	 * @return Date 改变后的时间
	 */
	public static Date getIncreaseDateByMinute(int minute) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + minute);
		return cal.getTime();
	}

	/**
	 * 跟据秒来增加时间
	 * 
	 * @author chentao 2018年10月15日
	 * @param second
	 *            要增加的秒
	 * @return Date 改变后的时间
	 */
	public static Date getIncreaseDateBySecond(int second) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) + second);
		return cal.getTime();
	}

	/**
	 * 反射获取对象属性值
	 * 
	 * @author chentao 2018年10月16日
	 * @param obj
	 *            被反射对象
	 * @return result 对象属性值
	 */
	public static String getInvokePropertiesValue(Object obj, String methodName) {
		String result = null;
		try {
			Method method = obj.getClass().getMethod(methodName);
			Object invoke = method.invoke(obj);
			if (null != invoke) {
				result = String.valueOf(invoke);
			}
		} catch (NoSuchMethodException e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		} catch (SecurityException e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		} catch (IllegalAccessException e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		} catch (IllegalArgumentException e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		} catch (InvocationTargetException e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		} catch (Exception e) {
			result = null;
			logger.error("getInvokeAccessToken method error." + e.getMessage());
		}
		return result;
	}

	/**
	 * MD5加密
	 * 
	 * @param inStr
	 * @return
	 * @throws Exception
	 */
	public static String strToMD5(String inStr) throws Exception {
		StringBuffer hexValue = new StringBuffer();
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (Exception e) {
			return "";
		}

		char[] charArray = inStr.toCharArray();
		byte[] byteArray = new byte[charArray.length];
		for (int i = 0; i < charArray.length; i++) {
			byteArray[i] = (byte) charArray[i];
		}
		byte[] md5Bytes = md5.digest(byteArray);
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = ((int) md5Bytes[i]) & 0xff;
			if (val < 16) {
				hexValue.append("0");
			}
			hexValue.append(Integer.toHexString(val));
		}
		return hexValue.toString();
	}

	/**
	 * MD5校验
	 * 
	 * @param str
	 * @param md5
	 * @return
	 * @throws Exception
	 */
	public static boolean verifyMD5(String str, String md5) throws Exception {
		String md5Str = strToMD5(str);
		if (md5Str.equalsIgnoreCase(md5)) {
			return true;
		}
		return false;
	}

	/**
	 * 获取消息属性文件中异常消息
	 * 
	 * @author chentao 2018年10月26日
	 * @param code
	 *            异常参数
	 * @return 异常消息内容
	 */
	public static String getPropCodeMessage(String code) {
		return getPropCodeMessage(code, "");
	}

	/**
	 * 获取消息属性文件中异常消息
	 * 
	 * @author chentao 2018年10月26日
	 * @param code
	 *            异常参数
	 * @return 异常消息内容
	 */
	public static String getMapProperties(String code) {
		return getMapProperties(code, "");
	}

	/**
	 * 获取消息属性文件中异常消息
	 * 
	 * @author chentao 2018年10月26日
	 * @param code
	 *            异常参数
	 * @return 异常消息内容
	 */
	public static String getMapProperties(String code, Object... arguments) {
		// 加载消息属性文件
		Properties errProp = TmompUtils.loadProperties("map.properties");
		Object prop = errProp.get(code);
		if (null != prop && !"".equals(prop)) {
			return MessageFormat.format(String.valueOf(prop), arguments);
		}
		return "";
	}

	/**
	 * 获取消息属性文件中异常消息
	 * 
	 * @author chentao 2018年10月26日
	 * @param code
	 *            异常参数
	 * @return 异常消息内容
	 */
	public static String getPropCodeMessage(String code, Object... arguments) {
		// 加载消息属性文件
		Properties errProp = TmompUtils.loadProperties("language_cn.properties");
		Object prop = errProp.get(code);
		if (null != prop && !"".equals(prop)) {
			return MessageFormat.format(String.valueOf(prop), arguments);
		}
		return "";
	}

	/**
	 * 获取二维码序列编号
	 * 
	 * @author yangzaitao 2018年11月6日
	 * @return
	 */
	public static String getQrCodeByUUId() {
		int machineId = 1;// 最大支持1-9个集群机器部署
		int hashCodeV = UUID.randomUUID().toString().hashCode();
		if (hashCodeV < 0) {// 有可能是负数
			hashCodeV = -hashCodeV;
		}
		// 0 代表前面补充0
		// 4 代表长度为4
		// d 代表参数为正数型
		String uuid = machineId + String.format("%012d", hashCodeV);
		// uuid + 时间毫秒数
		return uuid + System.currentTimeMillis();
	}

	/**
	 * base转明文
	 * 
	 * @author ZhangGuoWei 2018年11月9日
	 * @param baseData
	 * @return
	 */
	public static String undoBase64(String baseData) {
		byte[] data = null;
		String result = null;
		if (baseData != null) {
			BASE64Decoder decoder = new BASE64Decoder();
			try {
				data = decoder.decodeBuffer(baseData);
				result = new String(data, "utf-8");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
	 * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值
	 * 
	 * @author chentao 2018年12月20日
	 * @param request
	 *            请求对象
	 * @return ip 真实IP地址
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = "";
		try {
			ip = request.getHeader("x-forwarded-for");
			if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
				// 多次反向代理后会有多个ip值，第一个ip才是真实ip
				if (ip.indexOf(",") != -1) {
					ip = ip.split(",")[0];
				}
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_CLIENT_IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("X-Real-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
			logger.debug("客户端ip: " + ip);
		} catch (Exception e) {
			logger.error("getIpAddr error. " + e.getMessage());
		}
		return ip;
	}

	/**
	 * 组织编码生成
	 * 
	 * @return
	 */
	public synchronized static String getOrgCode() {
		String orgCode = "";
		SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		String temp = sf.format(new Date());
		int random = (int) (Math.random() * 10000);
		if (random < 1000) {
			String random1 = "0" + random;
			orgCode = orgCode + temp + random1;
		} else {
			orgCode = orgCode + temp + random;
		}
		return orgCode;
	}
	
	/**
	 * 去除字符串首尾出现的某个字符.
	 * @param source 源字符串.
	 * @param element 需要去除的字符.
	 * @return String.
	 */
	public static String trimFirstAndLastChar(String source,String element){
		boolean beginIndexFlag = true;
		boolean endIndexFlag = true;
		do{
			int beginIndex = source.indexOf(element) == 0 ? 1 : 0;
			int endIndex = source.lastIndexOf(element) + 1 == source.length() ? source.lastIndexOf(element) : source.length();
			source = source.substring(beginIndex, endIndex);
			beginIndexFlag = (source.indexOf(element) == 0);
			endIndexFlag = (source.lastIndexOf(element) + 1 == source.length());
		} while (beginIndexFlag || endIndexFlag);
		return source;
	}
	
    /**
     * 将元为单位的转换为分 替换小数点，支持以逗号区分的金额
     *
     * @param amount
     * @return
     */
    public static String changeBranch(String amount) {
        String currency = amount.replaceAll("\\$|\\￥|\\,", ""); // 处理包含, ￥
        // 或者$的金额
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }
    
}
